
#include "iostream"
#include <bitset>
#include <vector>
#include "f_extern.h"
using namespace std;

int delete_note(int parent_num_block,int child_num_block)
{

	char name[10];
	int num_next = 0;
	int num_chld;
	int size,last_block_size;
	int cur_note;
	int cur_block,prev_block;
	int moved;
	header head;
	header chld_head;
	header parent_head;
	string path;
	string chld_path;
	FILE *ptr;
	FILE *fd;
		
	sprintf(name,"./.%d",parent_num_block);	
	path = root_dir; path.append(name);
	fd = fopen(path.data(),"rb");
	fread(&parent_head,sizeof(header),1,fd);
	fclose(fd);
	
	size = parent_head.size;
	cur_block = prev_block = num_next =  parent_head.data_block;
	do
	{
		sprintf(name,"./.%d",num_next);	
		path = root_dir; path.append(name);
		fd = fopen(path.data(),"rb");
		size -= (block_size-sizeof(int));
		fseek(fd,-sizeof(int),SEEK_END);
		fread(&num_next,sizeof(int),1,fd);
		fclose(fd);
		if(num_next!=0)
		{
			prev_block = cur_block; cur_block = num_next;
		}	
	}while(num_next!=0);
	size += (block_size-sizeof(int));
	
	sprintf(name,"./.%d",cur_block);	
	path = root_dir; path.append(name);
	fd = fopen(path.data(),"rb+");
	if(size == sizeof(int))
	{
		fseek(fd,0,SEEK_SET);
		fread(&moved,sizeof(int),1,fd);
		fclose(fd);
		sprintf(name,"./.%d",prev_block);	
		path = root_dir; path.append(name);
		fd = fopen(path.data(),"rb+");
		fseek(fd,-sizeof(int),SEEK_END);
		cur_block = 0;
		fwrite(&cur_block,sizeof(int),1,fd);
		fclose(fd);
	}
	else
	{
		fseek(fd,(size-sizeof(int)),SEEK_SET);
		fread(&moved,1,sizeof(int),fd);
		fclose(fd);
	}
	if(moved!=child_num_block)
	{
		size = parent_head.size;
		num_next =  parent_head.data_block;
		do
		{
			sprintf(name,"./.%d",num_next);	
			path = root_dir; path.append(name);
			fd = fopen(path.data(),"rb+");
			
			for(int i=0;i<parent_head.size&&block_size-(sizeof(int));i++)
			{
				fread(&cur_note,1,sizeof(int),fd);
				if(cur_note == child_num_block)
				{
					num_next=0;
					break;
				}
			}
			if(cur_note != child_num_block)
			
			{
				size -= (block_size-sizeof(int));
				fseek(fd,-sizeof(int),SEEK_END);
				fread(&num_next,sizeof(int),1,fd);
				fclose(fd);
		
			}		
		}while(num_next!=0);
		
		if(cur_note != child_num_block)
		{
			fclose(fd);
			return 1;
		}
		else
		{
			fseek(fd,-sizeof(int),SEEK_CUR);
			fwrite(&moved,1,sizeof(int),fd);
			fclose(fd);
		}
	}
	sprintf(name,"./.%d",parent_num_block);	
	path = root_dir; path.append(name);
	fd = fopen(path.data(),"rb+");
	parent_head.size-=sizeof(int);
	set_time(&parent_head);
	fseek(fd,0,SEEK_SET);
	fwrite(&parent_head,sizeof(header),1,fd);
	fclose(fd);
	return 0;

}

int move_file(int src_prev_block, int src_block, int dst_block)
{

	char name[10];
	int num_next = 0;
	int size,last_block_size;
	int cur_note;
	int cur_block,prev_block;
	int moved;
	header head;
	header chld_head;
	header parent_head;
	string path;
	string chld_path;
	FILE *ptr;
	FILE *fd;
		
	delete_note(src_prev_block,src_block);

	sprintf(name,"./.%d",dst_block);	
	path = root_dir; path.append(name);
	fd = fopen(path.data(),"rb+");
	fread(&parent_head,sizeof(header),1,fd);
	fclose(fd);

	num_next = parent_head.data_block; size = parent_head.size;
	prev_block = num_next;
	do
	{
		sprintf(name,"./.%d",num_next);	
		path = root_dir; path.append(name);
		fd = fopen(path.data(),"rb+");
		size -= (block_size-sizeof(int));
		fseek(fd,-sizeof(int),SEEK_END);
		fread(&num_next,sizeof(int),1,fd);
		fclose(fd);	
	}while(num_next!=0);
	
	if(size == 0)
	{
		num_next = get_free_block();
		fd = fopen(path.data(),"rb+");
		fseek(fd,-sizeof(int),SEEK_END);
		fwrite(&num_next,sizeof(int),1,fd);
		fclose(fd);

		sprintf(name,"./.%d",num_next);	
		path = root_dir; path.append(name);
		fd = fopen(path.data(),"rb+");
		fwrite(&src_block,sizeof(int),1,fd);

		num_next = 0;
		fseek(fd,-sizeof(int),SEEK_END);
		fwrite(&num_next,sizeof(int),1,fd);
		fclose(fd);

	}
	else
	{
		
		size += (block_size-sizeof(int));
		fd = fopen(path.data(),"rb+");
		fseek(fd,size,SEEK_SET);
		fwrite(&src_block,sizeof(int),1,fd);
		fclose(fd);
	}

	sprintf(name,"./.%d",dst_block);	
	path = root_dir; path.append(name);
	fd = fopen(path.data(),"rb+");
	parent_head.size+=sizeof(int);
	fwrite(&parent_head,sizeof(header),1,fd);
	fclose(fd);
	return 0;
}

int find_dir(string dir_name, int base_block,int type )
{
	char name[10];
	int num_next = 0;
	int i,j;
	int num_chld;
	int cur_block_size,last_block_size;
	int tmp_size;
	int tmp_variant = -1;
	header head;
	header new_dir;
	sprintf(name,"./.%d",base_block);
	string path = root_dir; path.append(name);
	string chld_path;
	FILE *ptr;
	FILE *fd = fopen(path.data(),"rb");
	fread(&head,sizeof(header),1,fd);
	fclose(fd);
	num_next = head.data_block;	
	tmp_size = head.size;
	do
	{
		sprintf(name,"./.%d",num_next);
		path = root_dir; path.append(name);
		fd = fopen(path.data(),"rb");
		for(j=0;j<head.size && j<block_size-(sizeof(int)); j+=sizeof(int))
		{
			fread(&num_chld,sizeof(int),1,fd);
			sprintf(name,"./.%d",num_chld);
			chld_path = root_dir; chld_path.append(name);
			
			ptr = fopen(chld_path.data(),"rb");
			fread(&new_dir,sizeof(header),1,ptr);
			
			fclose(ptr);
			
			if(strcmp(new_dir.name,dir_name.data())==0 && (new_dir.type ==type || type ==-1))
			{
				fclose(fd);
				if(type==-1 && new_dir.type == root_dir_type)
					return num_chld;
				else if(type==-1)
					tmp_variant = num_chld;
			}
		

		}
		head.size -= (block_size-sizeof(int));
		fseek(fd,-sizeof(int),SEEK_END);
		fread(&num_next,sizeof(int),1,fd);
		fclose(fd);
	}while(num_next!=0);
		
	if(tmp_variant != -1)
		return tmp_variant;
	else
		return -1;
}


int main(int argc, char* argv[])
{	
	char* _f_ = "[move]";
	int next_dir_num = 0;
	int i;
	int src_block,dst_block,src_prev_block;
	FILE* config = NULL; 
	FILE* block = NULL;
	string src,dst;
	string host_file;
	vector<string> src_dir_set;
	header dir;
	string dir_path;
	if (argc != 4){
#ifdef PRINT_MSG
		printf("%s: Use move  root src dst\n",_f_);
#endif
		return 2;
	}

		root_dir = argv[1];
		make_build_map(1);
		src = argv[2];
		dst = argv[3];

		parse_path(src);
		if(dir_set.size() == 0)
		{
#ifdef PRINT_MSG
	printf("%s: cant move root dir %s.\n",_f_,src.data());
#endif	
			return 7;
		}
		
		src_prev_block = 1;
		for( i = 0;i<dir_set.size()-1;i++)
		{
			src_prev_block = find_dir(dir_set[i],src_prev_block,0);
			if(src_prev_block<0){
#ifdef PRINT_MSG
	printf("%s:Directory/File not exist %s.\n",_f_,src.data());
#endif	
			return 3;
			}	
		}
		next_dir_num = find_dir(dir_set[dir_set.size()-1],src_prev_block,-1);
		if(next_dir_num<0)
		{
#ifdef PRINT_MSG
	printf("%s:Directory/File not exist %s.\n",_f_,src.data());
#endif	
		return 4;
		}	
		src_block = next_dir_num;
		src_dir_set =  dir_set;
		dir_set.clear();
		parse_path(dst);

		if(dir_set.size()>=src_dir_set.size())
		{
			for(i = 0; i<src_dir_set.size() ;i++)
			{
		
				if(src_dir_set[i].compare(dir_set[i])==0)
					break;
			}
			if(i<src_dir_set.size())
			{
#ifdef PRINT_MSG
	printf("%s: Can't move directory into his own sub directory  %s %s\n",_f_,src.data(),dst.data());
#endif	
				return 6;
			}
		}		

		next_dir_num = 1;
		for( i = 0;i<dir_set.size();i++)
		{
			next_dir_num = find_dir(dir_set[i],next_dir_num,0);
			if(next_dir_num<0) 
			{
#ifdef PRINT_MSG
	printf("%s:Directory/File not exist %s.\n",_f_,dst.data());
#endif	
				return 5;
			}	
		}
		
		dst_block= next_dir_num;
		if( move_file(src_prev_block,src_block,dst_block) <0) return 6;
		else return 0;
}


